
import * as d3 from 'd3'
var chart
var layout
function initChart(divId) {
  let chart = {}
  chart.padding = {
    left: 10,
    right: 30,
    top: 10,
    bottom: 10
  }
  chart.divHeight = document.getElementById(divId).offsetHeight -
    chart.padding.top -
    chart.padding.bottom
  chart.divWidth = document.getElementById(divId).offsetWidth -
    chart.padding.left -
    chart.padding.right

  chart.svg = d3
    .select('#' + divId)
    .append('svg')
    .attr('width', chart.divWidth +
      chart.padding.left +
      chart.padding.right
    )
    .attr('height', chart.divHeight +
      chart.padding.top +
      chart.padding.bottom
    )
    .attr('class', 'steelChart')
  let color = [
    'rgb(0, 204, 0)',
    'rgb(238, 201, 0)',
    'rgb(255, 69, 0)',
    'rgb(255, 0, 0)',
    'rgb(142, 56, 142)',
    'rgb(139, 0, 0)'
  ]

  let colorange = ['0-50', '51-100', '101-150', '151-200', '201-300', '300+']
  let gLegend = chart.svg.selectAll('.legend')
    .data(color)
    .enter()
    .append('g')
    .attr('class', 'legend')
    .on('click', function(_, d) {
      let dom = d3.select(this)
      if (parseFloat(dom.style('opacity')) === 1) {
        dom.style('opacity', 0.1)
      } else {
        dom.style('opacity', 1)
      }
      let selectedIndex = []
      chart.svg.selectAll('.legend').each(function(d) {
        let dom = d3.select(this)
        if (parseFloat(dom.style('opacity')) === 1) {
          selectedIndex.push(d)
        }
      })

      chart.svg.selectAll('.cityDot')
        .style('opacity', 0)
        .filter(function(o) {
          if (selectedIndex.indexOf(d3.select(this).style('fill')) !== -1) {
            return o
          }
        })
        .style('opacity', 1)
    })
  gLegend.append('rect')
    .attr('x', chart.divWidth + chart.padding.right + chart.padding.left - 40)
    .attr('y', (_, i) => chart.divHeight + chart.padding.top - (color.length - i) * 11)
    .attr('width', 32)
    .attr('height', 10)
    .style('fill', d => d)
  chart.svg.append('text')
    .attr('x', chart.divWidth + chart.padding.right + chart.padding.left - 32)
    .attr('y', chart.divHeight + chart.padding.top - 68)
    .attr('font-size', 8)
    .text('AQI')
  gLegend.append('text')
    .attr('x', chart.divWidth + chart.padding.right + chart.padding.left - 40)
    .attr('y', (_, i) => chart.divHeight + chart.padding.top - (color.length - i) * 11 + 9)
    .attr('font-size', 8)
    .text((_, i) => colorange[i])
  return chart
}

function initLayout(chart) {
  let layout = {}
  layout.itemWidth = chart.divWidth / 2
  layout.itemHeight = chart.divHeight / 7
  layout.Radi = Math.min(layout.itemWidth, layout.itemHeight) / 2
  layout.color = function(i) {
    // let mycolor = ['#949483', '#f47b7b', '#9f1f5c', '#ef9020', '#00af3e',
    //   '#85b7e2', '#29245c', '#ffd616', '#e5352b', '#e990ab', '#0081b4',
    //   '#96cbb3', '#91be3e', '#39a6dd']
    let newColor = ['#8db5d3', '#f7c3b0', '#a1ede9', '#ffa05a', '#c492fd', '#3baeff',
      '#aed8ff', '#69bcaf', '#f2e280', '#d4cff7', '#fa8170', '#8f89ff', '#93d47f', '#ffc34e']
    return newColor[i % 14]
  }
  layout.polluColor = function(d) {
    let mainpollution = ['PM2.5', 'PM10', 'SO2', 'NO2', 'CO', 'O3']
    let pollutioncolor = ['#deb89e', '#997c61', '#7b6b57', '#654047', '#3e3123', '#c1888c']
    return pollutioncolor[mainpollution.indexOf(d.split('(')[0])]
  }
  return layout
}

function renderRing(svg, layout, data, category) {
  let p = ['NO2(微克每立方米)', 'CO(毫克每立方米)', 'PM2.5(微克每立方米)', 'PM10(微克每立方米)',
    'O3(微克每立方米)', 'SO2(微克每立方米)']
  let pollution = data['data'][0].data.filter(d => {
    let keys = Object.keys(d)[0].split('_').map(o => p.indexOf(o))
    if (Math.abs(keys[1] - keys[0]) > 1) {
      return d
    }
  })
  layout.p = p
  layout.polluAtmosArc = {}
  let ringData = data['data'][0].data.filter(d => {
    let keys = Object.keys(d)[0].split('_').map(o => p.indexOf(o))
    if (Math.abs(keys[1] - keys[0]) === 1 || (keys[0] === 0 && keys[1] === p.length - 1)) {
      return d
    }
  })

  layout.polluScale = function(pollu) {
    let p = ['NO2(微克每立方米)', 'CO(毫克每立方米)', 'PM2.5(微克每立方米)', 'PM10(微克每立方米)',
      'O3(微克每立方米)', 'SO2(微克每立方米)']
    let angle = [30, 90, 150, 210, 270, 330]
    return angle[p.indexOf(pollu)] * Math.PI / 180
  }

  let line = d3.lineRadial()
    .radius(function() {
      return layout.Radi - 10
    })
    .angle(function(d) {
      return d
    })
  let arc = d3.arc()
    .innerRadius(layout.Radi - 10)
    .outerRadius(layout.Radi - 10)
  let cluster = svg.select('.thisCluster')
  if (cluster.empty()) {
    cluster = svg.append('g')
      .attr('class', 'thisCluster')
      .attr('transform', 'translate(' + layout.itemWidth * 0.5 + ',' + layout.itemHeight * 0.5 + ')')
  }

  let polluRelation = cluster.select('.relatons')
  if (polluRelation.empty()) {
    polluRelation = cluster.append('g')
      .attr('class', 'relatons')
  }

  let gPollu = polluRelation.selectAll('.relation')
    .data(pollution)

  gPollu.transition()
    .duration(750)
    .attr('stroke-width', function(d) {
      return d[Object.keys(d)[0]] * 5
    })

  gPollu.enter()
    .append('path')
    .attr('class', 'relation')
    .attr('d', function(d) {
      let keys = Object.keys(d)[0].split('_').map(o => layout.polluScale(o))
      return line(keys)
    })
    .attr('stroke', 'black')
    .attr('stroke-width', function(d) {
      return d[Object.keys(d)[0]] * 5
    })
    .attr('fill', 'white')
    .style('opacity', 0.1)

  let gClsuter = cluster.selectAll('.pollution')
    .data(ringData, d => Object.keys(d)[0])

  gClsuter.transition()
    .duration(750)
    .style('stroke', layout.color(category))

  let enterNode = gClsuter.enter()
    .append('g')
    .attr('class', 'pollution')

  enterNode.append('path')
    .attr('d', function(d, i) {
      let keys = Object.keys(d)[0].split('_')
      if (i === 1) {
        return arc({
          'startAngle': layout.polluScale(keys[1]) + 0.15,
          'endAngle': layout.polluScale(keys[0]) + Math.PI * 2 - 0.15
        })
      }
      return arc({
        'startAngle': layout.polluScale(keys[0]) + 0.15,
        'endAngle': layout.polluScale(keys[1]) - 0.15
      })
    })
    .style('stroke', layout.color(category))
    .style('stroke-width', function(d) {
      return d[Object.keys(d)[0]] * 5
    })
    .style('fill', 'none')
    .append('title')
    .text(function(d) {
      let keys = Object.keys(d)[0].split('_')
      return keys[0].split('(')[0] + '与' + keys[1].split('(')[0] +
       '的相关系数: \n' + parseFloat(d[Object.keys(d)[0]]).toFixed(2)
    })

  cluster.selectAll('.index')
    .data(p, d => d)
    .enter()
    .append('circle')
    .attr('class', 'index')
    .attr('cx', function(d) {
      let angle = layout.polluScale(d)
      return (layout.Radi - 10) * Math.sin(angle)
    })
    .attr('cy', function(d) {
      let angle = layout.polluScale(d)
      return (layout.Radi - 10) * Math.cos(angle)
    })
    .attr('r', 3)
    .style('fill', function(d) {
      return layout.polluColor(d)
    })
    .append('title')
    .text(String)
}

function renderAtmos(svg, layout, data) {
  let arc = d3.arc()
    .innerRadius(layout.Radi - 5)
    .outerRadius(layout.Radi - 1)

  let colors = function(d) {
    let atmos = ['RH(%)', 'PSFC(Pa)', '风速', '风向', '摄氏温度']
    let myColor = ['#fce37e', '#98dcf3', '#0260eb', '#Ob44co', '#fb570b']
    return myColor[atmos.indexOf(d)]
  }

  let atmosScale = function(pollu) {
    let p = ['PM2.5(微克每立方米)', 'PM10(微克每立方米)', 'SO2(微克每立方米)',
      'NO2(微克每立方米)', 'CO(毫克每立方米)', 'O3(微克每立方米)'
    ]
    let angle = [5, 65, 125, 185, 245, 305]
    return angle[p.indexOf(pollu)] * Math.PI / 180
  }
  let angleScale = function(data, sum) {
    return (Math.abs(data) / sum) * (50 * Math.PI / 180)
  }

  let polluAtmosData = layout.p.map(function(d) {
    let atmos = data.filter(function(o) {
      return Object.keys(o)[0].indexOf(d) !== -1
    })
    return {'pollution': d, 'atmos': atmos}
  })

  let pollution = svg.selectAll('.polluAtmos')
    .data(polluAtmosData, d => d.pollution)
    .enter()
    .append('g')
    .attr('class', 'polluAtmos')
    .attr('transform', 'translate(' + layout.itemWidth * 0.5 + ',' + layout.itemHeight * 0.5 + ')')

  let gPolluAtmos = pollution.selectAll('.atmos')
    .data(function(d) {
      let sum = 0
      d.atmos.map((o, i) => {
        sum += Math.abs(o[Object.keys(o)[0]])
        if (i > 0) {
          let index = i - 1
          o._exData = 0
          while (index >= 0) {
            o._exData += Math.abs(d.atmos[index][Object.keys(d.atmos[index])[0]])
            index -= 1
          }
        }
      })
      d.atmos.map(function(o) {
        o.sum = sum
      })
      return d.atmos
    }, function(d) {
      return Object.keys(d)[0]
    })

  gPolluAtmos.transition()
    .duration(750)
    .attr('d', function(d, i) {
      let key = Object.keys(d)[0]
      let angle = angleScale(d[Object.keys(d)[0]], d.sum)
      let exAngle = 0
      if (i > 0) {
        exAngle = angleScale(d._exData, d.sum)
      }
      let sAngle = atmosScale(key.split('_')[0]) + exAngle
      return arc({
        'startAngle': sAngle,
        'endAngle': sAngle + angle
      })
    })

  gPolluAtmos.enter()
    .append('path')
    .attr('class', 'atmos')
    .attr('d', function(d, i) {
      let key = Object.keys(d)[0]
      let angle = angleScale(d[Object.keys(d)[0]], d.sum)
      let exAngle = 0
      if (i > 0) {
        exAngle = angleScale(d._exData, d.sum)
      }
      let sAngle = atmosScale(key.split('_')[0]) + exAngle
      return arc({
        'startAngle': sAngle,
        'endAngle': sAngle + angle
      })
    })
    .style('fill', d => {
      let atmos = Object.keys(d)[0].split('_')[1]
      return colors(atmos)
    })
}

function renderPots(svg, layout, data) {
  // let color = [
  //   '#00FF00',
  //   '#FFFF00',
  //   '#FF8C00',
  //   '#FF0000',
  //   '#FF00FF',
  //   '#800080'
  // ]
  // color = ['#84c45e', '#f9d92a', '#fda300', '#ff3406', '#cf0032', '#49224f']
  let color = [
    '#00CC00',
    '#EEC900',
    '#FF4500',
    '#FF0000',
    '#8E388E',
    '#8B0000'
  ]
  let cities = svg.select('.cityDots')
  if (cities.empty()) {
    cities = svg.append('g')
      .attr('class', 'cityDots')
  }

  let gDots = cities.selectAll('.cityDot')
    .data(data.city, d => d.city_name)

  gDots.transition()
    .duration(750)
    .attr('cx', function(d) {
      return layout.itemWidth * 0.5 + (layout.itemWidth / 3) * d.x
    })
    .attr('cy', function(d) {
      return layout.itemHeight * 0.5 + (layout.itemHeight / 3) * d.y
    })

  gDots.enter()
    .append('circle')
    .attr('class', 'cityDot')
    .attr('cx', function(d) {
      return layout.itemWidth * 0.5 + (layout.itemWidth / 3) * d.x
    })
    .attr('cy', function(d) {
      return layout.itemHeight * 0.5 + (layout.itemHeight / 3) * d.y
    })
    .attr('r', 2)
    .style('fill', function(d) {
      if (d.AQI >= 0 && d.AQI <= 50) {
        return color[0]
      }
      if (d.AQI > 50 && d.AQI <= 100) {
        return color[1]
      }
      if (d.AQI > 100 && d.AQI <= 150) {
        return color[2]
      }
      if (d.AQI > 150 && d.AQI <= 200) {
        return color[3]
      }
      if (d.AQI > 200 && d.AQI <= 300) {
        return color[4]
      }
      if (d.AQI > 300) {
        return color[5]
      }
    })
    .append('title')
    .text(d => d.city_name)

  gDots.exit()
    .transition()
    .duration(750)
    .attr('r', 0)
    .remove()
}

export function Steel(divId, data) {
  let _render = {}
  if (chart === undefined) {
    chart = initChart(divId)
    layout = initLayout(chart)
  }
  _render.cluster = ''
  _render.renderChart = function() {
    let cluster = chart.svg.selectAll('.cityCluster')
      .data(data, d => d.category)

    cluster.each(function(d) {
      let svg = d3.select(this)
      renderRing(svg, layout, d, d.category)
      renderPots(svg, layout, d)
      renderAtmos(svg, layout, d.data[1].data)
    })

    _render.cluster = cluster.enter()
      .append('g')
      .attr('class', 'cityCluster')
      .attr('transform', function(_, i) {
        return 'translate(' + (chart.padding.left + layout.itemWidth * (i % 2)) + ',' +
          (chart.padding.top + layout.itemHeight * (i % 7)) + ')'
      })
      .each(function(d) {
        let svg = d3.select(this)
        renderRing(svg, layout, d, d.category)
        renderPots(svg, layout, d)
        renderAtmos(svg, layout, d.data[1].data)
      })
  }

  _render.selectedCity = function(city) {
    d3.select('svg.steelChart').selectAll('.cityCluster').each(function() {
      let svg = d3.select(this)
      svg.selectAll('.cityDot')
        .style('opacity', 0)
        .filter(function(o) {
          if (city.indexOf(o.city_name) !== -1) {
            return o
          }
        })
        .style('opacity', 1)
    })
  }
  _render.filterByCluster = function(clsuter) {
    d3.select('svg.steelChart').selectAll('.cityCluster').style('opacity', 0.2)
      .filter(function(d) {
        if (clsuter.indexOf(d.category) !== -1) {
          return d
        }
      })
      .style('opacity', 1)
  }
  return _render
}
